package com.example.rxactivity;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

public class FromActivity extends AppCompatActivity {

    @BindView(R.id.btn1)
    Button btn1;
    @BindView(R.id.btn2)
    Button btn2;
    @BindView(R.id.tvShow)
    TextView tvShow;
    @BindView(R.id.btn3)
    Button btn3;
    @BindView(R.id.btn4)
    Button btn4;
    @BindView(R.id.btn5)
    Button btn5;
    @BindView(R.id.btn6)
    Button btn6;
    @BindView(R.id.btn7)
    Button btn7;
    @BindView(R.id.btn8)
    Button btn8;

    private CompositeDisposable compositeDisposable = new CompositeDisposable();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_from);
        ButterKnife.bind(this);
    }

    @OnClick({R.id.btn1, R.id.btn2, R.id.btn3, R.id.btn4, R.id.btn5, R.id.btn6
            , R.id.btn7, R.id.btn8})
    public void onViewClicked(View view) {
        tvShow.setText("");
        switch (view.getId()) {
            case R.id.btn1:
                FomArray();
                break;
            case R.id.btn2:
                FomCallable();
                break;
            case R.id.btn3:
                FromFuture();
                break;
            case R.id.btn4:
                FromIterable();
                break;
            case R.id.btn5:
                defer();
                break;
            case R.id.btn6:
                timer();
                break;
            case R.id.btn7:
                interval();
                break;
            case R.id.btn8:
                intervalRange();
                break;
        }
    }

    private void intervalRange() {
        tvShow.setText("可以指定发送事件的开始值和数量，其他与 interval() 的功能一样 .take(10) 到了10结束循环"
                + "\n 17:44:03.537 accept:  0's"
                + "\n 17:44:04.537 accept:  1's"
                + "\n 17:44:05.537 accept:  2's"
                + "\n Disposable disposable = Observable.interval(1, 1, TimeUnit.SECONDS)\n" +
                "                .subscribeOn(Schedulers.io())\n" +
                "                .take(10)\n" +
                "                .observeOn(AndroidSchedulers.mainThread())\n" +
                "                .subscribe(new Consumer<Long>() {\n" +
                "                               @Override\n" +
                "                               public void accept(Long aLong) throws Exception {\n" +
                "                                   Log.d(\"main\", \"accept: 剩余秒数 \" + aLong + \"'s\");\n" +
                "                               }\n" +
                "                           });\n" +
                "        compositeDisposable.add(disposable);");

        Disposable disposable = Observable.interval(1, 1, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .take(10)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        Log.d("main", "accept: 剩余秒数 " + aLong + "'s");
                    }
                });
        compositeDisposable.add(disposable);
    }

    private void interval() {
        tvShow.setText("每隔一段时间就会发送一个事件，这个事件是从0开始，不断增1的数字"
                + "/n 17:41:58.734 inteval--> 0"
                + "/n 17:41:59.734 inteval--> 1"
                + "/n 17:42:00.734 inteval--> 3"
                + "\n  Disposable disposable = Observable.interval(1, TimeUnit.SECONDS)\n" +
                "                .subscribe(new Consumer<Long>() {\n" +
                "                    @Override\n" +
                "                    public void accept(Long aLong) throws Exception {\n" +
                "                        Log.d(\"main\", \"accept: inteval--> \" + aLong);\n" +
                "                    }\n" +
                "                });\n" +
                "        compositeDisposable.add(disposable);");
        Disposable disposable = Observable.interval(1, TimeUnit.SECONDS)
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        Log.d("main", "accept: inteval--> " + aLong);
                    }
                });
        compositeDisposable.add(disposable);
    }

    @SuppressLint("SetTextI18n")
    private void timer() {
        tvShow.setText("当到指定时间后就会发送一个 0L 的值给观察者。到了10秒时 就会接收到 一个0的内容"
                + "\n timer --> 0"
                + "\n  Disposable disposable = Observable.timer(10, TimeUnit.SECONDS)\n" +
                "                .subscribe(new Consumer<Long>() {\n" +
                "                    @Override\n" +
                "                    public void accept(Long aLong) throws Exception {\n" +
                "                        Log.d(\"main\", \"accept: timer --> \"+aLong);     \n" +
                "                    }\n" +
                "                });");
        Disposable disposable = Observable.timer(10, TimeUnit.SECONDS)
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        Log.d("main", "accept: timer --> " + aLong);
                    }
                });
    }

    // i 要定义为成员变量
    Integer i = 100;

    @SuppressLint("SetTextI18n")
    private void defer() {
        tvShow.setText("这个方法的作用就是直到被观察者被订阅后才会创建被观察者。" +
                "最终打印结果为 200 300 400 因为传入100的时候 观察者还没订阅"
                + "\n  Observable<Integer> observable = Observable.defer(new Callable<ObservableSource<? extends Integer>>() {\n" +
                "            @Override\n" +
                "            public ObservableSource<? extends Integer> call() throws Exception {\n" +
                "                return Observable.just(i);\n" +
                "            }\n" +
                "        });\n" +
                "        i = 200;\n" +
                "        Observer observer = new Observer<Integer>() {\n" +
                "            @Override\n" +
                "            public void onSubscribe(Disposable d) {\n" +
                "\n" +
                "            }\n" +
                "\n" +
                "            @Override\n" +
                "            public void onNext(Integer o) {\n" +
                "                Log.d(\"main\", \"onNext:  defer-->\" + o);\n" +
                "            }\n" +
                "\n" +
                "            @Override\n" +
                "            public void onError(Throwable e) {\n" +
                "\n" +
                "            }\n" +
                "\n" +
                "            @Override\n" +
                "            public void onComplete() {\n" +
                "\n" +
                "            }\n" +
                "        };\n" +
                "        observable.subscribe(observer);\n" +
                "        i = 300;\n" +
                "        observable.subscribe(observer);\n" +
                "        i = 400;\n" +
                "        observable.subscribe(observer);");

        Observable<Integer> observable = Observable.defer(new Callable<ObservableSource<? extends Integer>>() {
            @Override
            public ObservableSource<? extends Integer> call() throws Exception {
                return Observable.just(i);
            }
        });
        i = 200;
        Observer observer = new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Integer o) {
                Log.d("main", "onNext:  defer-->" + o);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        };
        observable.subscribe(observer);
        i = 300;
        observable.subscribe(observer);
        i = 400;
        observable.subscribe(observer);

    }

    private void FromIterable() {
        tvShow.setText("直接发送一个 List 集合数据给观察者"
                + "\n 17:27:48.903 FromIterable--> 0"
                + "\n 17:27:48.903 FromIterable--> 1"
                + "\n 17:27:48.903 FromIterable--> 2"
                + "\n  List<Integer> list = new ArrayList<>();\n" +
                "        list.add(0);\n" +
                "        list.add(1);\n" +
                "        list.add(2);\n" +
                "\n" +
                "        Disposable disposable = Observable.fromIterable(list)\n" +
                "                .subscribe(new Consumer<Integer>() {\n" +
                "                    @Override\n" +
                "                    public void accept(Integer integer) throws Exception {\n" +
                "                        Log.d(\"main\", \"accept: FromIterable--> \" + integer);\n" +
                "                    }\n" +
                "                });\n" +
                "        compositeDisposable.add(disposable);");

        List<Integer> list = new ArrayList<>();
        list.add(0);
        list.add(1);
        list.add(2);

        Disposable disposable = Observable.fromIterable(list)
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                        Log.d("main", "accept: FromIterable--> " + integer);
                    }
                });
        compositeDisposable.add(disposable);
    }

    private void FromFuture() {

        tvShow.setText("Future 的作用是增加了 cancel() 等方法操作 Callable，它可以通过 get() 方法来获取 " +
                "Callable 返回的值。"
                + "\n FromFuture-->返回的结果"
                + "\n  FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {\n" +
                "            @Override\n" +
                "            public String call() throws Exception {\n" +
                "                return \"返回的结果\";\n" +
                "            }\n" +
                "        });\n" +
                "\n" +
                "        Disposable disposable = Observable.fromFuture(futureTask)\n" +
                "                .doOnSubscribe(new Consumer<Disposable>() {\n" +
                "                    @Override\n" +
                "                    public void accept(Disposable disposable) throws Exception {\n" +
                "                        futureTask.run();\n" +
                "                    }\n" +
                "                })\n" +
                "                .subscribe(new Consumer<String>() {\n" +
                "                    @Override\n" +
                "                    public void accept(String s) throws Exception {\n" +
                "                        Log.d(\"main\", \"accept: FromFuture-->\"+s);\n" +
                "                    }\n" +
                "                });\n" +
                "        compositeDisposable.add(disposable);");

        FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "返回的结果";
            }
        });

        Disposable disposable = Observable.fromFuture(futureTask)
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
                        futureTask.run();
                    }
                })
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.d("main", "accept: FromFuture-->" + s);
                    }
                });
        compositeDisposable.add(disposable);
    }

    public void FomArray() {

        tvShow.setText("这个方法和 just() 类似，只不过 fromArray 可以传入多于10个的变量，并且可以传入一个数组。"
                + "\n 17:06:29.285 FromArray -->这"
                + "\n 17:06:29.286 FromArray -->是"
                + "\n 17:06:29.286 FromArray -->FromArray"
                + "\n String list[] = {\"这\", \"是\", \"FromArray\"};\n" +
                "        Disposable disposable = Observable.fromArray(list)\n" +
                "                .observeOn(AndroidSchedulers.mainThread())\n" +
                "                .subscribeOn(Schedulers.io())\n" +
                "                .subscribe(new Consumer<String>() {\n" +
                "                    @Override\n" +
                "                    public void accept(String s) throws Exception {\n" +
                "                        Log.d(\"main\", \"accept: FromArray -->\" + s);\n" +
                "                    }\n" +
                "                });\n" +
                "        compositeDisposable.add(disposable);");
        String list[] = {"这", "是", "FromArray"};
        Disposable disposable = Observable.fromArray(list)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.d("main", "accept: FromArray -->" + s);
                    }
                });
        compositeDisposable.add(disposable);

    }

    public void FomCallable() {
        tvShow.setText("回一个结果值，这个结果值就是发给观察者的。"
                + "\n 17:08:17.448 FromCallable-->这是FromCallable练习"
                + "\n Disposable disposable = Observable.fromCallable(new Callable<String>() {\n" +
                "            @Override\n" +
                "            public String call() throws Exception {\n" +
                "                return \"这是FromCallable练习\";\n" +
                "            }\n" +
                "        })\n" +
                "                .subscribeOn(Schedulers.io())\n" +
                "                .observeOn(AndroidSchedulers.mainThread())\n" +
                "                .subscribe(new Consumer<String>() {\n" +
                "                               @Override\n" +
                "                               public void accept(String s) throws Exception {\n" +
                "                                   Log.d(\"main\", \"accept:  FromCallable-->\" + s);\n" +
                "                               }\n" +
                "                           }, new Consumer<Throwable>() {\n" +
                "                               @Override\n" +
                "                               public void accept(Throwable throwable) throws Exception {\n" +
                "\n" +
                "                               }\n" +
                "                           }\n" +
                "                );\n" +
                "        compositeDisposable.add(disposable);");
        Disposable disposable = Observable.fromCallable(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "这是FromCallable练习";
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                               @Override
                               public void accept(String s) throws Exception {
                                   Log.d("main", "accept:  FromCallable-->" + s);
                               }
                           }, new Consumer<Throwable>() {
                               @Override
                               public void accept(Throwable throwable) throws Exception {

                               }
                           }
                );
        compositeDisposable.add(disposable);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (compositeDisposable != null) {
            compositeDisposable.clear();
            compositeDisposable.dispose();
            compositeDisposable = null;
        }
    }


}
